/*
 * @Description: PGV100二维码传感器通信线程
 * @Author: Dryad
 * @Date: 2019-08-01 15:09:33
 */

#pragma once

#include <rtthread.h>

/*
* PGV传感器地址为0,串口通信格式为115200，8e1
* 通信为一收一发格式
*
* 处理Tag标签，码带和色带数据，但码带数据处理不够灵活，需修改
*
* PGV自身坐标系定义
*   安装座为y轴正方向
*   指示灯一侧为x轴正方向
*   顺时针为正
*
* PGV安装坐标系定义
*   安装座为x轴正方向
*   指示灯一侧为y轴正方向
*   逆时针为正
*
* 读取色带，码带和二维码数据时，需将数据转换至PGV自身坐标系内
* 再根据传感器安装坐标系，转换为车体坐标
*/

#ifdef __cplusplus
extern "C"
{
#endif

    void PGV_Thread_Init(float x, float y, float theta); /* PGV收发线程初始化，输入变量为传感器在车体中的坐标 */

    /* PGV传感器的指令 */
    enum PGV_CMD_Mode
    {
        Set_Dir_R = 0x01,    /* 选择右边颜色轨道 */
        Set_Dir_L = 0x02,    /* 选择左边颜色轨道 */
        Set_Dir_Best = 0x03, /* 选择对比度最好的颜色轨道 */
        Read_PGV_Data,       /* 读PGV数据 */
        Set_Color_B,         /* 选择蓝色轨道 */
        Set_Color_R,         /* 选择红色轨道 */
        Set_Color_G          /* 选择绿色轨道 */
    };
    rt_err_t PGV_Send(enum PGV_CMD_Mode cmd); /* 发送指定命令事件给PGV发线程 */

    /* 对于传感器来说，优先级：Tag标签=位置码带>色带 */
    /* 软件上优先检查Tag标签，对Tag标签和位置码带不做区分，因此粘贴时需注意 */
    enum PGV_Target
    {
        Colored_Tape,    /* 色带 */
        Code_Tape,       /* 位置码带 */
        Data_Matrix_Tag, /* Tag标签 */
        NO_Target        /* 没有识别到码带、色带、Tag标签 */
    };

    /* 二维码数据 */
    struct DM_Data_Struct
    {
        rt_uint32_t tag_control_num; /* 存放Tag标签号 */
        float x;                     /* x坐标 */
        float y;                     /* y坐标 */
        float angle;                 /* 角度坐标 */
    };

    /* 位置码带数据 */
    struct Code_Tape_Data_Struct
    {
        float x;       /* x坐标 */
        float delta_y; /* y坐标偏差值 */
        float angle;   /* 角度坐标 */
    };
    /* 色带数据 */
    struct Colored_Tape_Date_Struct
    {
        float angle; /* 通过色带读取的角度数据 */
        float delta; /* 通过色带读取的位置偏差 */
    };

    /* PGV传感器数据 */
    union PGV_Data {
        struct DM_Data_Struct dm_data;                     /* 二维码数据 */
        struct Code_Tape_Data_Struct code_tape_data;       /* 位置条码数据 */
        struct Colored_Tape_Date_Struct colored_tape_data; /* 色带数据 */
    };

    /* PGV报警信息 */
    union PGV_Wrong_Code {
        struct
        {
            char pgv_specification_wrong : 1; /* 发现非PGV规格的二维码 */
            char too_close : 1;               /* 读头离码带太近 */
            char too_far : 1;                 /* 读头离码带太远 */
            char reserve_3_4 : 2;             /* 保留 */
            char excessive_rotation : 1;      /* 读头相对码带旋转或偏转过大 */
            char low_contrast : 1;            /* 码对比度太低 */
            char reserve_7_8 : 2;             /* 保留 */
            char excessive_temperature : 1;   /* 温度过高 */
            char code_tape_fork : 1;          /* 位置码带靠近在分叉或交叉处 */
            char code_tape_wrong : 1;         /* 发现超过规定的码带 */
            char reserve_11_14 : 4;           /* 保留 */
        };
        rt_uint16_t code; /* 错误代码 */
    };

    /* PGV应答数据 */
    struct PGV_Response_Data
    {
        enum PGV_CMD_Mode cmd;          /* 指令 */
        enum PGV_Target target;         /* 读取到的目标 */
        union PGV_Data data;            /* 数据 */
        union PGV_Wrong_Code warn_code; /* 警告代码，错误代码自行对照PGV说明书，将来会使用程序完成解析 */
    };

    /* 返回PGV应答数据,RT_EOK 成功；-RT_ERROR 失败  */
    rt_err_t Return_PGV_Data(struct PGV_Response_Data *_response_data, rt_int32_t waittime);
    rt_uint32_t PGV_Cal_TAG(int x, int y);                       /* 根据x,y计算tag号 */
    void PGV_Cal_X_Y(int *x, int *y, const rt_uint32_t tag_num); /* 根据tag号计算x,y */
#ifdef __cplusplus
}
#endif
